<script setup lang="ts">
import {
  NForm,
  NFormItem,
  NInput,
  NButton,
  NSelect,
  useMessage,
  NModal,
  type FormItemRule,
  type FormInst,
  NTag,
  NScrollbar,
  NIcon,
  NDataTable,
  NPagination,
  NImage,
  NTreeSelect,
  type TreeSelectOption,
  type DataTableColumns,
  type SelectOption
} from 'naive-ui'
import { ref, reactive, onMounted, shallowRef, watchEffect, watch, h } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import useRouteReplace from '@/hooks/useRouteReplace'
import FixedAction from '@/components/FixedAction.vue'
import { sendRequest } from '@/utils/api'
import type { HttpResponse, HttpResponsePagination } from '@/utils/http'
import VScope from '@/views/OA/Common/Scope.vue'
import { CloseOutlined } from '@vicons/material'
import type { DicTreeModel } from '@/api/dic'
import axios from 'axios'
import useFlush from '@/hooks/useFlush'
import useRouteParam from '@/hooks/useRouteParam'
import VBackImg from '@/assets/images/back.png'

const route = useRoute()
const router = useRouter()
const message = useMessage()
const routeReplace = useRouteReplace(route.query.redirect as string)
// const isCreate = route.query.type === 'c'
const isDetail = route.query.type === 'r'
const isUpdate = route.query.type === 'u'
useRouteParam('id', main)
useFlush('flushWithClueAdd', () => queryTableData(true))

interface FormData {
  id: number
  userName: string | null
  collectTypeCode: string | null
  collectTypeCodeArr: string[] | null
  collectorTags: string | null
  collectorTypeCode: string | null
  idNo: string | null
  idType: string | null
  scopeOrPeopleList: Contact[] | null
  phone: string | null
  regionCode: string | null
  regionCodeCity: string | null
  regionCodeProvince: string | null
  remark: string | null
  transferList: TransferPerson[] | null
  address: string | null
}

interface InfoModel extends FormData {
  id: number
  createdBy: string
  createdTime: string
  delFlag: number
  collectorTypeName: string
  collectTypeName: string
  collectorFlag: number
  donateNum: number
  idTypeName: string
  regionName: string
  sourceCode: string
  sourceName: string
}

interface TransferPerson {
  transferName: string | null
  transferPhone: string | null
}

interface Contact {
  identifyingId: string
  typeName: string
  parentId: string
  typeCode: string
  deptId: string
  fullId: string
}

const formInst = ref<FormInst | null>(null)
const formData = reactive({
  transferList: [] as TransferPerson[]
} as FormData)

watchEffect(() => {
  formData.collectTypeCode = formData.collectTypeCodeArr?.join(',') ?? null
})

const submitLoading = ref(false)
const handleSubmit = () => {
  formInst.value?.validate(async (error) => {
    if (error) return
    submitLoading.value = true

    try {
      const [error, res] = await sendRequest<HttpResponse>({
        module: 'collector',
        api: isUpdate ? 'update' : 'save',
        override: {
          data: formData
        }
      })
      if (error) throw error
      if (res.code !== 0) throw new Error(res.msg)
      message.success(res.msg)
      window.flags.flushCollectionTable = true
      routeReplace()
    } catch (error) {
      if (!(error instanceof Error)) return
      message.error(error.message)
    } finally {
      submitLoading.value = false
    }
  })
}

const handleUpdateCollectorTags = (v: string[]) => {
  if (v && v.length === 0) {
    formData.collectorTags = null
    return
  }
  formData.collectorTags = v.join(',')
}

// 类型下拉框
const typeOptions = shallowRef<DicTreeModel[]>([])
const typeLoading = ref(false)
const queryTypeOptions = async () => {
  typeLoading.value = true
  try {
    const [error, res] = await sendRequest<HttpResponse<DicTreeModel[]>>({
      module: 'dic',
      api: 'getTree',
      override: {
        params: {
          dicCode: 'A63'
        }
      }
    })

    if (error) throw error
    if (res.code !== 0) throw new Error(res.msg)
    typeOptions.value = res.data[0] ? res.data[0].children || [] : []
  } catch (error) {
    console.error(error)
  } finally {
    typeLoading.value = false
  }
}

// 标签下拉框
const tagOptions = shallowRef<SelectOption[]>([])
const tagLoading = ref(false)
const queryTagOptions = async () => {
  tagLoading.value = true
  try {
    const [error, res] = await sendRequest<HttpResponse<SelectOption[]>>({
      module: 'collection',
      api: 'tagOptions',
      override: {
        params: {
          tagUseCode: 'A6901'
        }
      }
    })

    if (error) throw error
    if (res.code !== 0) throw new Error(res.msg)
    ;(res.data || []).forEach((e) => (e.disabled = isDetail))
    tagOptions.value = res.data || []
  } catch (error) {
    console.error(error)
  } finally {
    tagLoading.value = false
  }
}

// 证件类型下拉框
const paperTypeOptions = shallowRef<DicTreeModel[]>([])
const paperTypeLoading = ref(false)
const queryPaperTypeOptions = async () => {
  paperTypeLoading.value = true
  try {
    const [error, res] = await sendRequest<HttpResponse<DicTreeModel[]>>({
      module: 'dic',
      api: 'getTree',
      override: {
        params: {
          dicCode: 'A37'
        }
      }
    })

    if (error) throw error
    if (res.code !== 0) throw new Error(res.msg)
    paperTypeOptions.value = res.data[0] ? res.data[0].children || [] : []
  } catch (error) {
    console.error(error)
  } finally {
    paperTypeLoading.value = false
  }
}

// 版本类型下拉框
const versionTypeOptions = ref<TreeSelectOption[]>([])
const versionTypeLoading = ref(false)
const queryVersionTypeOptions = async () => {
  versionTypeLoading.value = true
  try {
    const [error, res] = await sendRequest<HttpResponse<TreeSelectOption[]>>({
      module: 'collector',
      api: 'versionListTreeAll',
      override: {
        params: {
          statusCode: 'A4901'
        }
      }
    })

    if (error) throw error
    if (res.code !== 0) throw new Error(res.msg)
    handleVersionOptionsLeaf(res.data as unknown as VersionOption[])
    versionTypeOptions.value = res.data.length ? res.data : []
  } catch (error) {
    console.error(error)
  } finally {
    versionTypeLoading.value = false
  }
}
interface VersionOption {
  childList?: VersionOption[]
  classificationCode: string
  classificationName: string
  isLeaf: boolean
}
// 如果 childList是空数组，则此节点是leaf为true的节点，并且把childList置为undefined
const handleVersionOptionsLeaf = (options: VersionOption[]) => {
  options.forEach((e) => {
    if (e.childList?.length) {
      handleVersionOptionsLeaf(e.childList)
    } else {
      e.isLeaf = true
      e.childList = undefined
    }
  })
  return options
}

// 区域下拉框
const provinceFeature = useQueryRegionOptions()
const cityFeature = useQueryRegionOptions()
const areaFeature = useQueryRegionOptions()
function watchRegionChange() {
  watch(
    () => formData.regionCodeProvince,
    (v) => {
      formData.regionCodeCity = null
      formData.regionCode = null
      cityFeature.options.value = []
      if (v) cityFeature.query(v)
    }
  )
  watch(
    () => formData.regionCodeCity,
    (v) => {
      formData.regionCode = null
      areaFeature.options.value = []
      if (v) areaFeature.query(v)
    }
  )
}
function useQueryRegionOptions() {
  const options = ref<SelectOption[]>([])
  const loading = ref(false)
  const source = shallowRef(axios.CancelToken.source())

  const query = async (code: string) => {
    source.value.cancel('cancel')
    source.value = axios.CancelToken.source()

    try {
      loading.value = true
      const [error, res] = await sendRequest<HttpResponse<SelectOption[]>>({
        module: 'sysRegion',
        api: 'list',
        uri: {
          code
        },
        override: {
          cancelToken: source.value.token
        }
      })

      if (error) throw error
      if (res.code !== 0) throw new Error(res.msg)
      options.value = res.data || []
    } catch (error) {
      if (axios.isCancel(error)) return (options.value = [])
      if (error instanceof Error) message.error(error.message)
    } finally {
      loading.value = false
    }
  }
  return { options, loading, query }
}

// 获取详情
const info = ref<InfoModel | null>(null)
const queryInfo = async () => {
  try {
    const [error, res] = await sendRequest<HttpResponse<InfoModel>>({
      module: 'collector',
      api: 'info',
      uri: {
        id: route.params.id as string
      }
    })

    if (error) throw error
    if (res.code !== 0) throw new Error(res.msg)
    info.value = res.data
    formData.id = info.value.id
    formData.userName = info.value.userName
    formData.collectTypeCodeArr = info.value.collectTypeCode?.split(',') ?? null
    formData.collectorTags = info.value.collectorTags
    formData.collectorTypeCode = info.value.collectorTypeCode
    formData.idNo = info.value.idNo
    formData.idType = info.value.idType
    formData.phone = info.value.phone
    formData.regionCode = info.value.regionCode
    formData.regionCodeCity = info.value.regionCodeCity
    formData.regionCodeProvince = info.value.regionCodeProvince
    formData.remark = info.value.remark
    formData.scopeOrPeopleList = info.value.scopeOrPeopleList
    formData.address = info.value.address
    formData.transferList = info.value.transferList
    if (!formData.collectorTags) formData.collectorTags = null
    if (formData.regionCodeProvince) cityFeature.query(formData.regionCodeProvince)
    if (formData.regionCodeCity) areaFeature.query(formData.regionCodeCity)
    watchRegionChange()
  } catch (error) {
    console.error(error)
  }
}

const paginationReactive = reactive({
  page: 1,
  pageSize: 10,
  showSizePicker: true,
  pageSizes: [10, 20, 50, 100, 500],
  itemCount: 0,
  onChange: (page: number) => {
    paginationReactive.page = page
    queryTableData()
  },
  onUpdatePageSize: (pageSize: number) => {
    paginationReactive.pageSize = pageSize
    paginationReactive.page = 1
    queryTableData()
  }
})

type ClueTableRow = any
const tableData = ref<ClueTableRow[]>([])
const tableLoading = ref(false)
const queryTableData = async (flush = false) => {
  if (flush) paginationReactive.page = 1
  try {
    tableLoading.value = true
    const [error, res] = await sendRequest<HttpResponsePagination<ClueTableRow>>({
      module: 'collector',
      api: 'clueList',
      override: {
        params: {
          limit: paginationReactive.pageSize,
          page: paginationReactive.page,
          collectorId: route.params.id as string
        }
      }
    })
    if (error) throw error
    if (res.code !== 0) throw new Error(res.msg)

    tableData.value = res.data.list
    paginationReactive.itemCount = res.data.totalCount
  } catch (error) {
    console.log(error)
  } finally {
    tableLoading.value = false
  }
}
const columns: DataTableColumns<ClueTableRow> = [
  {
    title: '线索编号',
    key: 'clueNumber'
  },
  {
    title: '线索名称',
    key: 'clueName'
  },
  {
    title: '线索状态',
    key: 'statusName'
  },
  {
    title: '联系方式',
    key: 'concatUserPhone'
  },
  {
    title: '线索提供时间',
    key: 'provideTime'
  },
  {
    title: '线索提供方式',
    key: 'provideType'
  },
  {
    title: '征集部对接人',
    key: 'collectionConcatUser',
    ellipsis: {
      tooltip: {
        width: 300
      }
    }
  },
  {
    title: '修改时间',
    key: 'updatedTime'
  },
  {
    title: '操作',
    key: 'action',
    align: 'center',
    render: (e) =>
      h(
        NButton,
        {
          quaternary: true,
          type: 'primary',
          onClick: () => {
            router.push({
              name: 'clueManagementDetail',
              params: {
                id: e.id
              },
              query: {
                redirect: route.fullPath
              }
            })
          }
        },
        {
          default: () => '详情'
        }
      )
  }
]

onMounted(main)

function main() {
  if (isUpdate || isDetail) queryInfo()
  else watchRegionChange()
  if (isDetail) queryTableData()
  queryTagOptions()
  queryTypeOptions()
  queryPaperTypeOptions()
  queryVersionTypeOptions()
  provinceFeature.query('100000000000')
}

// 内部联系人
const contactsModalVisible = ref(false)
const handleContactsModalSubmit = (v: Contact[]) => {
  formData.scopeOrPeopleList = v
  contactsModalVisible.value = false
}
const handleDeleteContact = (index: number) => {
  formData.scopeOrPeopleList?.splice(index, 1)
}

// 联络人
const handleDeleteTransfer = (index: number) => {
  formData.transferList?.splice(index, 1)
}
const handleAddTransfer = () => {
  formData.transferList?.push({
    transferName: null,
    transferPhone: null
  })
}

const limitRule = (len: number): FormItemRule => {
  return {
    trigger: ['blur', 'input'],
    message: `不能超过${len}字`,
    validator: (_, value) => (value ? value.length <= len : true)
  }
}
</script>

<template>
  <DetailFormProvider>
    <div class="collection-cur">
      <div class="cc-title">藏家{{ isDetail ? '详情' : isUpdate ? '编辑' : '新增' }}</div>

      <NForm
        ref="formInst"
        :model="formData"
        :disabled="isDetail"
        label-placement="left"
        require-mark-placement="left"
        :show-require-mark="!isDetail ? undefined : false"
        label-width="130px"
        class="cc-card"
      >
        <NFormItem
          label="单位/个人名称："
          path="userName"
          label-width="160rem"
          :rule="[
            {
              required: true,
              message: '单位/个人名称为必填项，请输入',
              trigger: ['blur', 'input']
            },
            limitRule(20)
          ]"
        >
          <NInput
            v-model:value="formData.userName"
            placeholder="请输入"
          />
        </NFormItem>
        <NFormItem
          label="类型："
          path="collectorTypeCode"
          :rule="{
            required: true,
            message: '类型为必填项，请选择',
            trigger: ['change', 'blur']
          }"
        >
          <NSelect
            v-model:value="formData.collectorTypeCode"
            :options="typeOptions"
            :loading="typeLoading"
            placeholder="请选择"
            filterable
            value-field="code"
            label-field="name"
          />
        </NFormItem>
        <!-- <NFormItem label="联系方式：">
          <NInput
            v-model:value="formData.phone"
            placeholder="请输入"
          />
        </NFormItem> -->
        <NFormItem
          label="区域（省-市-区）："
          label-width="160rem"
        >
          <NSelect
            v-model:value="formData.regionCodeProvince"
            placeholder="请选择省"
            clearable
            :options="provinceFeature.options.value"
            :loading="provinceFeature.loading.value"
            value-field="regionCode"
            label-field="shortName"
          />
          <NSelect
            v-model:value="formData.regionCodeCity"
            placeholder="请选择市"
            clearable
            :options="cityFeature.options.value"
            :loading="cityFeature.loading.value"
            value-field="regionCode"
            label-field="shortName"
          />
          <NSelect
            v-model:value="formData.regionCode"
            placeholder="请选择区"
            clearable
            :options="areaFeature.options.value"
            :loading="areaFeature.loading.value"
            value-field="regionCode"
            label-field="shortName"
          />
        </NFormItem>
        <NFormItem label="证件类型：">
          <NSelect
            v-model:value="formData.idType"
            :options="paperTypeOptions"
            :loading="paperTypeLoading"
            placeholder="请选择证件类型"
            filterable
            value-field="code"
            label-field="name"
          />
          <NInput
            v-model:value="formData.idNo"
            placeholder="请输入证件号"
          />
        </NFormItem>
        <NFormItem
          label="详细地址："
          label-width="160rem"
        >
          <NInput
            v-model:value="formData.address"
            placeholder="请输入"
          />
        </NFormItem>
        <NFormItem label="版本类型：">
          <NTreeSelect
            v-if="!isDetail"
            v-model:value="formData.collectTypeCodeArr"
            :options="versionTypeOptions"
            :loading="versionTypeLoading"
            multiple
            placeholder="请选择"
            clearable
            children-field="childList"
            label-field="classificationName"
            key-field="classificationCode"
          />
          <NInput
            v-else
            :value="info?.collectTypeName"
          />
        </NFormItem>
        <NFormItem
          label="标签："
          label-width="160rem"
          path="collectorTags"
          :rule="limitRule(50)"
        >
          <NSelect
            :value="formData.collectorTags?.split(',')"
            @update:value="handleUpdateCollectorTags"
            :options="tagOptions"
            :loading="tagLoading"
            multiple
            placeholder="请输入"
          />
        </NFormItem>
        <span></span>
        <NFormItem
          label="内部联系人："
          label-width="160rem"
        >
          <div
            v-if="!isDetail"
            class="contacts"
          >
            <NButton
              v-if="!isDetail"
              type="primary"
              ghost
              @click="contactsModalVisible = true"
            >
              选择内部联系人
            </NButton>
            <NScrollbar style="max-height: 210rem">
              <div
                v-show="formData.scopeOrPeopleList?.length"
                class="contacts-content"
              >
                <NTag
                  v-for="(contact, index) in formData.scopeOrPeopleList"
                  @close="handleDeleteContact(index)"
                  :key="index"
                  :closable="!isDetail"
                  :color="{ color: '#ffffff' }"
                  style="justify-content: space-between; gap: 0 10rem"
                >
                  {{ contact.typeName }}
                </NTag>
              </div>
            </NScrollbar>
          </div>
          <NInput
            v-else
            type="textarea"
            :value="formData.scopeOrPeopleList?.map((e) => e.typeName).join('; ')"
          />
        </NFormItem>

        <NFormItem
          v-if="isDetail"
          label="来源："
          :label-width="isDetail ? undefined : '160rem'"
        >
          <NInput
            :value="info?.sourceName"
            placeholder="/"
          />
        </NFormItem>
        <div
          class="transfers-wrapper"
          :style="isDetail ? 'grid-column: 1 / -1' : ''"
        >
          <NFormItem
            label="联系方式："
            :show-feedback="false"
            :label-width="isDetail ? '160rem' : undefined"
          >
            <NButton
              v-if="!isDetail"
              type="primary"
              ghost
              @click="handleAddTransfer"
            >
              联系人添加
            </NButton>
            <NInput
              v-else
              type="textarea"
              :value="
                formData.transferList
                  ?.map((e) => `${e.transferName}(${e.transferPhone || '/'})`)
                  .join('; ')
              "
            />
          </NFormItem>

          <NScrollbar
            v-if="!isDetail"
            style="max-height: 210rem"
          >
            <NFormItem
              v-for="(contact, index) in formData.transferList"
              :key="index"
              closable
              label="联络人："
              label-width="160rem"
              :path="`transferList[${index}]transferName`"
              :rule="[
                { required: true, message: '姓名为必填项，请输入', trigger: ['blur', 'input'] }
                // limitRule(20)
              ]"
            >
              <div class="transfers">
                <NInput
                  v-model:value="contact.transferName"
                  placeholder="请输入姓名"
                />
                <NInput
                  v-model:value="contact.transferPhone"
                  placeholder="请输入联系方式"
                  style="--n-border-error: var(--n-border)"
                />
                <NIcon
                  v-if="!isDetail"
                  :size="18"
                  @click="handleDeleteTransfer(index)"
                >
                  <CloseOutlined />
                </NIcon>
              </div>
            </NFormItem>
          </NScrollbar>
        </div>
        <NFormItem
          label="备注："
          label-width="160rem"
          path="remark"
          :rule="limitRule(200)"
          class="n-form-item--textarea"
        >
          <NInput
            v-model:value="formData.remark"
            type="textarea"
            placeholder="请输入"
            rows="5"
          />
        </NFormItem>
      </NForm>

      <template v-if="isDetail">
        <div class="br"></div>
        <div class="cc-title">
          <span>关联线索</span>
          <NButton
            type="primary"
            @click="
              $router.push({
                name: 'clueManagementAdd',
                query: {
                  collectorId: route.params.id as string,
                  redirect: $route.fullPath
                }
              })
            "
          >
            线索新增
          </NButton>
        </div>
        <div class="cc-card">
          <NDataTable
            :data="tableData"
            :columns="columns"
            :loading="tableLoading"
            bordered
          />
          <NPagination
            show-size-picker
            show-quick-jumper
            :page-sizes="paginationReactive.pageSizes"
            :item-count="paginationReactive.itemCount"
            :page="paginationReactive.page"
            :page-size="paginationReactive.pageSize"
            @update:page="paginationReactive.onChange"
            @update:page-size="paginationReactive.onUpdatePageSize"
          >
            <template #suffix>页</template>
            <template #prefix>
              <span style="font-size: 14px">共{{ paginationReactive.itemCount }}条</span>
            </template>
          </NPagination>
        </div>
      </template>
    </div>
  </DetailFormProvider>

  <FixedAction>
    <div
      class="collection-cur-buttons"
      :style="isDetail ? 'justify-content: flex-start' : undefined"
    >
      <template v-if="!isDetail">
        <NButton
          color="#999999"
          ghost
          :disabled="submitLoading"
          @click="routeReplace"
          style="width: 78px; height: 34px"
        >
          取消
        </NButton>

        <NButton
          color="#5FB17F"
          :disabled="submitLoading"
          :loading="submitLoading"
          @click="handleSubmit"
          style="width: 78px; height: 34px"
        >
          保存
        </NButton>
      </template>

      <NButton
        v-else
        ghost
        @click="routeReplace"
        :style="`width: 78px; height: 34px; color: #5fb17f`"
      >
        <template #icon>
          <NImage
            :src="VBackImg"
            :style="`width: 50rem; height: 50rem`"
            preview-disabled
          ></NImage>
        </template>
        返回
      </NButton>
    </div>
  </FixedAction>

  <NModal
    :auto-focus="false"
    v-model:show="contactsModalVisible"
    @close="contactsModalVisible = false"
  >
    <VScope
      @close="contactsModalVisible = false"
      @scopeSubmit="handleContactsModalSubmit"
      :default-list="formData.scopeOrPeopleList!"
      flat
    />
  </NModal>
</template>

<style scoped lang="scss">
.collection-cur {
  min-height: 100%;
  padding: 16rem 16rem 110rem;

  .cc-card {
    padding: 20rem;
    background-color: #ebeceb;
  }

  .cc-title {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 22px;
    font-family: PingFangSC, PingFang SC;
    font-weight: 500;
    color: #5fb17f;
    margin-bottom: 10rem;
  }

  .br {
    position: relative;
    width: 100%;
    padding: 30rem 0;

    &::after {
      content: '';
      position: absolute;
      width: 100%;
      top: 50%;
      left: 0;
      border-top: 1px dotted #bc9e70;
      transform: translateY(-50%);
    }
  }

  .n-form {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 6rem 30rem;
  }

  .n-form-item--textarea {
    grid-column: 1 / -1;
  }

  :deep(.n-scrollbar-container) {
    overscroll-behavior-y: contain;
  }
}

.collection-cur-buttons {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0 16rem;

  .n-button {
    width: 100rem;
    height: 50rem;
  }
}

.contacts {
  display: flex;
  flex-direction: column;
  gap: 10rem 0;

  .n-button {
    max-width: 126rem;
  }

  .contacts-content {
    display: grid;
    grid-template-columns: repeat(5, auto);
    gap: 10rem;
    padding: 15rem;
    background-color: #fff;
  }
}

.transfers-wrapper {
  display: flex;
  flex-direction: column;
  gap: 10rem;

  .transfers {
    display: flex;
    align-items: center;
    gap: 10rem;

    .n-icon {
      cursor: pointer;
    }
  }
}
</style>
